﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace BlueMarble.Genesis.Client.Standard.Forms
{
    public partial class Main : Form, global::Genesis.Common.Interfaces.IDataContainer, global::Genesis.Common.Interfaces.IHost
    {
        // The Global Data Set is simply a dataset that stores information that the framework
        // or any hosted applications might require. 
        // Hosted applications can also use this data set to store temporary data, and persist
        // portions of it to disk for offline functionality.
        protected System.Data.DataSet globalDataSet;
        protected global::Genesis.Common.Classes.GlobalDataSetFunctions globalDataSetFunctions;

        // A set of commands are loaded into memory for access by any hosted applications
        protected List<global::Genesis.Common.Interfaces.ICommandInfo> commands;

        public Main()
        {
            InitializeComponent();

            commands = new List<global::Genesis.Common.Interfaces.ICommandInfo>();
        }

        #region IHost Members

        public void SynchronizeApplicationRibbons()
        {
            try
            {
                DataTable applicationRibbonsTable = globalDataSet.Tables["Module_Ribbon"];

                foreach (DataRow ribbonRow in applicationRibbonsTable.Rows)
                {
                    if (findRibbonByName((string)ribbonRow["RibbonName"]) == null)
                    {
                        System.Windows.Forms.ToolStripMenuItem menuItem = new ToolStripMenuItem();

                        menuItem.Text = (string)ribbonRow["RibbonName"];

                        menuStrip.Items.Add(menuItem);

                        this.SynchronizeRibbonBars((Guid)ribbonRow["RibbonGuid"], menuItem);
                    }
                    else
                    {
                        this.SynchronizeRibbonBars((Guid)ribbonRow["RibbonGuid"], this.findRibbonByName((string)ribbonRow["RibbonName"]));
                    }
                }
            }
            catch
            {
                throw;
            }
        }

        public List<global::Genesis.Common.Interfaces.ICommandInfo> Commands
        {
            get
            {
                return commands;
            }
            set
            {
                commands = value;
            }
        }

        public global::Genesis.Common.Interfaces.ICommand ExecuteCommand(global::Genesis.Common.Interfaces.ICommandInfo Command)
        {
            try
            {
                Command.Command.Execute();

                Command.Command.ResetCommandParameters();
            }
            catch
            {
                throw;
            }

            return Command.Command;
        }

        public global::Genesis.Common.Interfaces.ICommand ExecuteCommand(global::Genesis.Common.Interfaces.ICommand Command)
        {
            try
            {
                Command.Execute();

                Command.ResetCommandParameters();
            }
            catch
            {
                throw;
            }

            return Command;
        }

        public global::Genesis.Common.Interfaces.ICommand ExecuteCommand(string CommandCode)
        {
            global::Genesis.Common.Interfaces.ICommand command = null;

            if (FindCommandByCode(CommandCode) != null)
            {
                command = ExecuteCommand(FindCommandByCode(CommandCode));
            }

            return command;
        }

        public global::Genesis.Common.Interfaces.ICommand ExecuteCommand(string CommandCode, params global::Genesis.Common.Classes.CommandParameter[] Parameters)
        {
            global::Genesis.Common.Interfaces.ICommandInfo command = FindCommandByCode(CommandCode);

            if (command != null)
            {
                command.Command.ResetCommandParameters();

                foreach (global::Genesis.Common.Classes.CommandParameter parameter in Parameters)
                {
                    command.Command.Parameters.Add(parameter);
                }

                ExecuteCommand(command);
            }

            return command.Command;
        }

        public global::Genesis.Common.Interfaces.ICommand ExecuteCommandUrl(string CommandUrl)
        {
            global::Genesis.Common.Interfaces.ICommand commandInterface = null;

            string commandUrl = CommandUrl;

            if (commandUrl.ToLower().StartsWith("genesis"))
            {
                string command = commandUrl.Replace("genesis://", "");
                command = command.Remove(command.IndexOf('?'), command.Length - command.IndexOf('?'));

                //commandUrl = commandUrl.Remove(0, commandUrl.IndexOf('?'));

                if (commandUrl.Split('?').Length > 1)
                {
                    string parameters = commandUrl.Split('?')[1];

                    parameters = parameters.Replace("%3f", "?");
                    parameters = parameters.Replace("%26", "&");

                    global::Genesis.Common.Classes.CommandParameter[] commandParameters = new global::Genesis.Common.Classes.CommandParameter[parameters.Split('&').Length];

                    int i = 0;

                    foreach (string parameter in parameters.Split('&'))
                    {
                        if ((parameter != null) || (parameter.Length != 0))
                        {
                            string _parameter = (parameter.IndexOf("=") >= 0) ? parameter : parameter.Replace("%3d", "=");

                            global::Genesis.Common.Classes.CommandParameter commandParameter = new global::Genesis.Common.Classes.CommandParameter(_parameter.Split('=')[0], _parameter.Split('=')[1]);

                            commandParameter.Value = ((string)commandParameter.Value).Replace("%3c%25", "<%");
                            commandParameter.Value = ((string)commandParameter.Value).Replace("%25%3e", "%>");
                            commandParameter.Value = ((string)commandParameter.Value).Replace("%3d", "=");
                            commandParameter.Value = ((string)commandParameter.Value).Replace("<%SessionGuid%>", GlobalDataSetFunctions.GetProperty("SessionGuid"));

                            commandParameters[i++] = commandParameter;
                        }
                    }

                    commandInterface = ExecuteCommand(command, commandParameters);
                }
                else
                {
                    commandInterface = ExecuteCommand(command);
                }
            }

            return commandInterface;
        }

        public global::Genesis.Common.Interfaces.IPage ActivePage
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public void CreateWindowFromPage(global::Genesis.Common.Interfaces.IPage Page)
        {
            try
            {
                global::Genesis.Client.Common.Classes.MdiChildBase mdiChild = new global::Genesis.Client.Common.Classes.MdiChildBase();

                global::Genesis.Common.Interfaces.IMdiChild mdiChildInterface = (global::Genesis.Common.Interfaces.IMdiChild)mdiChild;

                mdiChildInterface.Page = Page;

                this.CreateWindow(mdiChildInterface);
            }
            catch
            {
                throw;
            }
        }

        public void CreateWindow(global::Genesis.Common.Interfaces.IMdiChild MdiChild)
        {
            try
            {
                ((System.Windows.Forms.Form)MdiChild).MdiParent = this;

                ((System.Windows.Forms.Form)MdiChild).Show();
            }
            catch
            {
                throw;
            }
        }

        public void CreatePage(global::Genesis.Common.Interfaces.IPage Page)
        {
            throw new NotImplementedException();
        }

        public void UpdateNavigation()
        {
            try
            {
                if (this.ActiveMdiChild != null)
                {
                    toolStripButtonBack.Enabled = ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).CanBrowseBack();
                    toolStripButtonForward.Enabled = ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).CanBrowseForward();
                    toolStripButtonSave.Enabled = ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).CanSave();
                    toolStripButtonRefresh.Enabled = ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).CanRefresh();
                    toolStripButtonBusy.Enabled = ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).IsBusy();
                    toolStripButtonPrint.Enabled = ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).CanPrint();
                }
                else
                {
                    toolStripButtonBack.Enabled = false;
                    toolStripButtonForward.Enabled = false;
                    toolStripButtonSave.Enabled = false;
                    toolStripButtonRefresh.Enabled = false;
                    toolStripButtonBusy.Enabled = false;
                    toolStripButtonPrint.Enabled = false;
                }
            }
            catch
            {
                throw;
            }
        }

        public void UpdateTitle(global::Genesis.Common.Interfaces.IPage Page)
        {
            throw new NotImplementedException();
        }

        public void UpdateStatusBarText(string Text)
        {
            toolStripStatusLabel.Text = Text;
            Application.DoEvents();
        }

        public global::Genesis.Common.Classes.GlobalDataSetFunctions GlobalDataSetFunctions
        {
            get
            {
                return globalDataSetFunctions;
            }
            set
            {
                globalDataSetFunctions = value;
            }
        }

        #endregion

        #region IDataContainer Members

        public DataSet GlobalDataSet
        {
            get
            {
                return globalDataSet;
            }
            set
            {
                globalDataSet = value;

                globalDataSetFunctions = new global::Genesis.Common.Classes.GlobalDataSetFunctions(globalDataSet);
            }
        }

        public void SaveGlobalDataSet()
        {
            globalDataSet.WriteXml("datastore.xml");
        }

        public void LoadGlobalDataSet()
        {
            globalDataSet.ReadXml("datastore.xml");
        }

        #endregion

        public global::Genesis.Common.Interfaces.ICommandInfo FindCommandByCode(string Code)
        {
            global::Genesis.Common.Interfaces.ICommandInfo commandInfo = null;

            try
            {
                for (int i = 0; i < commands.Count; i++)
                {
                    if (commands[i].Code.ToLower() == Code.ToLower())
                    {
                        commandInfo = commands[i];
                    }
                }
            }
            catch
            {
                throw;
            }

            if (commandInfo == null)
            {
                MessageBox.Show("Your user does not have the required permissions to execute " + Code);
            }

            return commandInfo;
        }

        protected global::Genesis.Common.Interfaces.ICommandInfo findCommandByGuid(Guid CommandGuid)
        {
            try
            {
                for (int i = 0; i < this.commands.Count; i++)
                {
                    if (this.commands[i].Guid == CommandGuid)
                    {
                        return this.commands[i];
                    }
                }
            }
            catch
            {
                throw;
            }

            return null;
        }

        protected System.Windows.Forms.ToolStripMenuItem findRibbonByName(string MenuName)
        {
            try
            {
                foreach (System.Windows.Forms.ToolStripMenuItem item in menuStrip.Items)
                {
                    if (item.Text == MenuName)
                    {
                        return item;
                    }
                }
            }
            catch
            {
                throw;
            }

            return null;
        }

        public void ExecuteStartupScript()
        {
            try
            {
                global::Genesis.Client.Common.Classes.GenesisProvider genesisProvider = new global::Genesis.Client.Common.Classes.GenesisProvider();

                string startupScriptPath = (string)genesisProvider.ExecuteScalar("SELECT StartupScript FROM Security_User SU INNER JOIN Security_Session SS ON SS.UserGuid = SU.UserGuid WHERE SS.SessionGuid = @SessionGuid",
                    "GenesisConnectionString",
                    global::Genesis.Client.Common.WebService.Genesis.CommandType.Text,
                    "StartupScriptTable",
                    global::Genesis.Client.Common.Classes.DataParameterFactory.CreateParameter("@SessionGuid", globalDataSetFunctions.GetProperty("SessionGuid")));

                DownloadFile("startup.xml", startupScriptPath);

                System.Xml.XmlDocument startupScript = new System.Xml.XmlDocument();

                startupScript.Load(AppDomain.CurrentDomain.BaseDirectory + "\\startup.xml");

                System.Xml.XmlNodeList jobList = startupScript.DocumentElement.SelectNodes(".//job");

                foreach (System.Xml.XmlNode job in jobList)
                {
                    ExecuteCommandUrl(job.Attributes["command"].Value);
                }
            }
            catch
            {
                throw;
            }
        }

        protected void DownloadFile(string FileName, string FileUrl)
        {
            DialogResult retryResult = DialogResult.Retry;

            while (retryResult == DialogResult.Retry)
            {
                try
                {
                    if (!System.IO.Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\"))
                    {
                        System.IO.Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\");
                    }

                    System.Net.WebRequest webRequest = System.Net.WebRequest.CreateDefault(new Uri(FileUrl + "?CacheKiller=" + Guid.NewGuid().ToString()));

                    int retryCount = 0;
                    bool downloaded = false;
                    System.IO.FileStream streamWriter = null;
                    System.IO.Stream fileStream = null;

                    while (!downloaded)
                    {
                        try
                        {
                            fileStream = webRequest.GetResponse().GetResponseStream();

                            if ((FileUrl.ToLower().EndsWith("x")) &&
                                (!FileName.ToLower().EndsWith("x")))
                            {
                                FileName += "x";
                            }
                            streamWriter = System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "\\" + FileName);

                            downloaded = true;
                        }
                        catch
                        {
                            retryCount++;

                            if (retryCount >= 2)
                            {
                                downloaded = true;

                                retryResult = DialogResult.OK;

                                break;
                            }
                        }
                    }

                    if ((streamWriter != null) && (fileStream != null))
                    {
                        int value = fileStream.ReadByte();
                        int counter = 0;

                        while (value != -1)
                        {
                            streamWriter.WriteByte((byte)value);

                            value = fileStream.ReadByte();
                            counter++;
                        }

                        streamWriter.Close();

                        retryResult = DialogResult.OK;
                    }
                }
                catch
                {
                    throw;
                }
            }
        }

        public void SynchronizeRibbonBars(Guid RibbonGuid, ToolStripMenuItem MenuItem)
        {
            try
            {
                DataRow[] ribbonBars = globalDataSet.Tables["Module_RibbonBar"].Select(string.Format("RibbonGuid = '{0}'", RibbonGuid), "RibbonBarOrder ASC");

                foreach (DataRow ribbonBarRow in ribbonBars)
                {
                    ToolStripItem seperatorItem = new ToolStripSeparator();

                    MenuItem.DropDownItems.Add(seperatorItem);

                    this.SynchronizeBarItems((Guid)ribbonBarRow["RibbonBarGuid"], Guid.Empty, MenuItem);
                }
            }
            catch
            {
                throw;
            }
        }

        public void SynchronizeBarItems(Guid RibbonBarGuid, Guid ParentBarItemGuid, ToolStripItem RibbonBar)
        {
            try
            {
                DataRow[] barItems = globalDataSet.Tables["Module_BarItem"].Select(string.Format("(RibbonBarGuid = '{0}') AND (ParentBarItemGuid = '{1}')", RibbonBarGuid, ParentBarItemGuid), "BarItemOrder ASC");

                foreach (DataRow barItemRow in barItems)
                {
                    ToolStripItem barItem;

                    switch ((int)barItemRow["BarItemTypeId"])
                    {
                        case 0:
                            break;
                        case 1:
                            barItem = new ToolStripButton();
                            barItem.Text = (string)barItemRow["BarItemName"];

                            if (barItemRow["BarItemImage"] != DBNull.Value)
                            {
                                if (((string)barItemRow["BarItemImage"]).ToLower().EndsWith(".ico"))
                                {
                                    int pixelSize = (int)barItemRow["BarItemImageSize"];
                                    System.Drawing.Size size = new Size(pixelSize, pixelSize);
                                    System.Drawing.Icon ico = new Icon(AppDomain.CurrentDomain.BaseDirectory + @"\" + (string)barItemRow["BarItemImage"], size);
                                    //((ToolStripButton)barItem).Image = ico;
                                }
                                else if (((string)barItemRow["BarItemImage"]).ToLower().EndsWith(".png"))
                                {
                                    ((ToolStripButton)barItem).Image = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + @"\" + (string)barItemRow["BarItemImage"]);
                                }
                            }

                            if (barItemRow["CommandGuid"] != DBNull.Value)
                            {
                                barItem.Tag = this.findCommandByGuid((Guid)barItemRow["CommandGuid"]);
                            }

                            barItem.Click += new EventHandler(barItem_Click);

                            if (RibbonBar.GetType() == typeof(ToolStripMenuItem))
                            {
                                ((ToolStripMenuItem)RibbonBar).DropDownItems.Add(barItem);
                            }
                            else if (RibbonBar.GetType() == typeof(ToolStripButton))
                            {
                            }
                            else
                            {
                            }

                            SynchronizeBarItems(RibbonBarGuid, (Guid)barItemRow["BarItemGuid"], barItem);
                            break;
                        case 2:
                            break;
                        case 3:
                            break;
                        case 4:
                            break;
                        case 5:
                            break;
                        case 6:
                            break;
                        case 7:
                            break;
                        default:
                            break;
                    }
                }
            }
            catch
            {
                throw;
            }
        }

        void barItem_Click(object sender, EventArgs e)
        {
            try
            {
                object tag = ((ToolStripItem)sender).Tag;

                if ((tag != null) && (tag.GetType() == typeof(global::Genesis.Common.Classes.CommandInfoBase)))
                {
                    this.ExecuteCommand(((global::Genesis.Common.Interfaces.ICommandInfo)tag));
                }
            }
            catch
            {
                throw;
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void signoutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Restart();
        }

        private void toolStripButtonBack_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.ActiveMdiChild != null)
                {
                    ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).BrowseBack();
                }
            }
            catch
            {
                throw;
            }
        }

        private void toolStripButtonForward_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.ActiveMdiChild != null)
                {
                    ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).BrowseForward();
                }
            }
            catch
            {
                throw;
            }
        }

        private void toolStripButtonRefresh_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.ActiveMdiChild != null)
                {
                    ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).Refresh();
                }
            }
            catch
            {
                throw;
            }
        }

        private void toolStripButtonSave_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.ActiveMdiChild != null)
                {
                    ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).Save();
                }
            }
            catch
            {
                throw;
            }
        }

        private void toolStripButtonPrint_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.ActiveMdiChild != null)
                {
                    ((global::Genesis.Common.Interfaces.IMdiChild)this.ActiveMdiChild).Print();
                }
            }
            catch
            {
                throw;
            }
        }
    }
}
